package com.ngo.utils;

import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.lang.reflect.Field;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import static org.springframework.util.StringUtils.isEmpty;

public class HttpUtil {
	
	
	private static final Logger log = LoggerFactory.getLogger(HttpUtil.class);

	public static final String DEFAULT_FORM_CONTENT_TYPE = "application/x-www-form-urlencoded";

	public static final String JSON_CONTENT_TYPE = "application/json";

	public static final String CHARSET_CODE="UTF-8";

	public static String post(String url, Map<String,String> headers, Map<String,String> params){
		
		try {
			
            if(isEmpty(url)){
				
				throw new RuntimeException("http url 为空");
			}

			CloseableHttpClient client = HttpClients.createDefault();

			HttpPost httpPost = new HttpPost(url);

			if(headers!=null){
				
				for (String name : headers.keySet()) {

					httpPost.addHeader(name, headers.get(name).toString());
				}
			}
			
			if(params!=null){
				List<NameValuePair> nameValuesPairs = new ArrayList<NameValuePair>(params.size());
				
				for (String name : params.keySet()) {

					nameValuesPairs.add(new BasicNameValuePair(name, String.valueOf(params.get(name))));
				}
				httpPost.setEntity(new UrlEncodedFormEntity(nameValuesPairs, "UTF-8"));
			}

			log.info("HTTP POST REQUEST:URL {}",url);
			
			CloseableHttpResponse response = client.execute(httpPost);

			String body=EntityUtils.toString(response.getEntity()); 
			
			log.info("HTTP POST RESPONSE {}",body);
			
			return body;

		} catch (IOException e) {
			throw new RuntimeException("远程接口调用异常");
		}
	}
	
	public static String get(String url, Map<String, String> headers, Map<String, String> params) {

		try {

			if (isEmpty(url)) {

				throw new RuntimeException("http url 为空");
			}

			StringBuilder urlBuffer = new StringBuilder();

			urlBuffer.append(url);

			if (params != null) {

				urlBuffer.append("?");

				for (Iterator<String> iter = params.keySet().iterator();iter.hasNext();) {

					String key = iter.next();

					urlBuffer.append(key).append("=").append(params.get(key));

					if (iter.hasNext()) {

						urlBuffer.append("&");
					}
				}
			}

			CloseableHttpClient httpclient = HttpClients.createDefault();
			
			HttpGet httpGet = new HttpGet(urlBuffer.toString());
			if (headers != null) {

				for (String name : headers.keySet()) {

					httpGet.addHeader(name, headers.get(name).toString());
				}

			}

			log.info("HTTP GET REQUEST:URL {}",url);
			log.info("HTTP GET REQUEST:params {}",params);
			
			HttpResponse response = httpclient.execute(httpGet);

			HttpEntity responseEntity = response.getEntity();

			InputStream responseContent = responseEntity.getContent();

			BufferedReader reader = new BufferedReader(new InputStreamReader(responseContent, "UTF-8"));

			StringBuilder strBuffer = new StringBuilder();

			String temp = null;

			while ((temp = reader.readLine()) != null) {

				strBuffer.append(temp);
			}

			String responseStr = strBuffer.toString();
			
			log.info("HTTP GET RESPONSE: {}",responseStr);
			
			return responseStr;

		} catch (IOException e) {
			throw new RuntimeException("远程接口调用异常");
		}
	}
	public static String httpPost(String urlStr, String params, String charSet,Map<String, String> headParams, String contentType) {
		HttpURLConnection httpConn = null;
		try {
			byte[] data=params.getBytes(charSet);
			URL url=new URL(urlStr);
			httpConn=(HttpURLConnection)url.openConnection();
			httpConn.setRequestMethod("POST");
			httpConn.setRequestProperty("ContentType", contentType);
			httpConn.setRequestProperty("Content-Length", String.valueOf(data.length));
			//设置请求头参数
			if(headParams!=null){
				for(String key : headParams.keySet()){
					httpConn.setRequestProperty(key, headParams.get(key));
				}
			}
			httpConn.setDoInput(true);
			httpConn.setDoOutput(true);
			httpConn.setConnectTimeout(5000);// 连接超时
			httpConn.setReadTimeout(5000);// 读操作超时
			httpConn.connect();
			OutputStream os1=httpConn.getOutputStream();
			os1.write(data);
			os1.flush();
			os1.close();
			return getResponseResult(httpConn, urlStr, charSet);
		} catch(Exception ex) {
			if(ex instanceof java.net.ConnectException || ex instanceof java.net.SocketTimeoutException) {
				clearDNSCache();
			}
			ex.printStackTrace();
			log.error(urlStr, ex);
		} finally {
			if(null != httpConn) {
				httpConn.disconnect();
			}
		}
		return null;
	}

	private static String getResponseResult(HttpURLConnection httpConn, String urlStr, String charSet) throws IOException {
		String res=null;
		// 获得响应状态
		// int responseCode=httpConn.getResponseCode();
		byte[] buffer=new byte[1024];
		int len=-1;
		InputStream is=httpConn.getInputStream();
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		while((len=is.read(buffer)) != -1) {
			bos.write(buffer, 0, len);
		}
		res=bos.toString(charSet);
		is.close();
		bos.close();
		return res;
	}

	@SuppressWarnings("unchecked")
	public static void clearDNSCache() {
		try {
			Class clazz=java.net.InetAddress.class;
			final Field cacheField=clazz.getDeclaredField("addressCache");
			cacheField.setAccessible(true);
			final Object o=cacheField.get(clazz);
			Class clazz2=o.getClass();
			// final Field cachePolicyField = clazz2.getDeclaredField("policy");
			final Field cacheMapField=clazz2.getDeclaredField("cache");
			cacheMapField.setAccessible(true);
			final Map cacheMap=(Map)cacheMapField.get(o);
			// cachePolicyField.setAccessible(true);
			AccessController.doPrivileged(new PrivilegedAction<Object>() {

				public Object run() {
					try {
						synchronized (o) {// 同步是必须的,因为o可能会有多个线程同时访问修改。
							cacheMap.clear();// 这步比较关键，用于清除原来的缓存
							// cachePolicyField.setInt(o,0);//设置缓存的时间，单位秒(-1,永久缓存;0,不缓存;其它>0的值为缓存的秒数)
						}
					} catch (Throwable te) {
						throw new RuntimeException(te);
					}
					return null;
				}
			});
		} catch(Exception ex) {
		}
	}

	public static void main(String[] args){
		JSONObject obj = new JSONObject();
		obj.put("user_ticket","ZsKO8n51PV-FTRWPgQLzZU6uXN3TnnUnSbxyX_HcHbBs5JuT4bwfQYWcOp9FOO0gn16DRkyGwkd9Kq0rasDDsQ");
		String result = HttpUtil.httpPost("https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail?access_token=B4Uf8yaYsGYw_fRgdP_pXTeLF3JQZZfDRG6ppDZH1h2Wif2wTI0ZAnhV3HefIHfZUQyDlNXxvdaFjGkktdq557QwWJWSt_BaK2LbY1IULX6IesIWa29IwdOsVmJ_PQG0H-UZWrEO7XISpsj4nCbRzMdjQn4RSqRJrasEBB0SYu4exnqIdaYO_t_56LZ3q2iG0zyuwD0N-Vve_n0XksAvvA",obj.toJSONString(),
				HttpUtil.CHARSET_CODE,null,HttpUtil.JSON_CONTENT_TYPE);

		System.out.println(result);
	}

}
